package com.umessage.common.shiro;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;

import com.alibaba.fastjson.JSONObject;
import com.umessage.common.service.RedissonService;
import com.umessage.common.util.JsonWebTokenUtil;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;

public class JwtFilter extends FormAuthenticationFilter {

	// 用户端小程序
	public static final String CLIENT_MINI_PROGRAM = "client_mp";
	// 酒店端小程序
	public static final String HOTEL_MINI_PROGRAM = "hotel_mp";

	/**
	 * 设置 request 的键，用来保存 认证的 userID,
	 */
	private final static String USER_ID = "USER_ID";

	/**
	 * logger
	 */
	private static final Logger LOGGER = LoggerFactory.getLogger(JwtFilter.class);

	/**
	 * shiro权限拦截核心方法 返回true允许访问resource，
	 *
	 * @param request
	 * @param response
	 * @param mappedValue
	 * @return
	 */
	@Override
	protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
		String token = getRequestToken((HttpServletRequest) request);
		
		//测试token
		if("wxxq".equals(token)) {
			request.setAttribute("openid", "oLiYB5QaLfMxQ33i3tmJ2VW42DtY");
//			request.setAttribute("issuer", hotelId);
			request.setAttribute("audience", "client_mp");
			request.setAttribute("subject", "94a1f11d-27ce-4702-881c-b820e82eef8e");
			request.setAttribute("type", "2");
			return true;
		}
		
		//测试token
		/*if("999999999".equals(token)) {
			request.setAttribute("openid", "oLiYB5QaLfMxQ33i3tmJ2VW42DtY");
//			request.setAttribute("issuer", hotelId);
			request.setAttribute("audience", "client_mp");
			request.setAttribute("subject", "177");
			request.setAttribute("type", "3");
			return true;
		}*/
		
		try {
			// 检查 token 有效性
			// ExpiredJwtException JWT已过期
			// SignatureException JWT可能被篡改
			Jwts.parser().setSigningKey(JsonWebTokenUtil.SECRET_KEY).parseClaimsJws(token).getBody();
		} catch (Exception e) {
			// 身份验证失败，返回 false 将进入onAccessDenied 判断是否登陆。
//            onLoginFail(response);
			return false;
		}

		Claims claims = JsonWebTokenUtil.parseJwt(token, JsonWebTokenUtil.SECRET_KEY);

		String id = claims.getId();
		String issuer = claims.getIssuer();
		String audience = claims.getAudience();
		String subject = claims.getSubject();
		String type = (String) claims.get("type");

		request.setAttribute("openid", id);
		request.setAttribute("issuer", issuer);
		request.setAttribute("audience", audience);
		request.setAttribute("subject", subject);
		request.setAttribute("type", type);

		return true;
	}

	/**
	 * 当访问拒绝时是否已经处理了； 如果返回true表示需要继续处理； 如果返回false表示该拦截器实例已经处理完成了，将直接返回即可。
	 *
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	@Override
	protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
		if (isLoginRequest(request, response)) {
			if (isLoginSubmission(request, response)) {
				return executeLogin(request, response);
			} else {
				return true;
			}
		} else {
			onLoginFail(response);
			return false;
		}
	}

	/**
	 * 鉴定失败，返回错误信息
	 * 
	 * @param token
	 * @param e
	 * @param request
	 * @param response
	 * @return
	 */
	@Override
	protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e, ServletRequest request,
			ServletResponse response) {
		try {
			((HttpServletResponse) response).setStatus(HttpStatus.BAD_REQUEST.value());
			response.getWriter().print("账号活密码错误");
		} catch (IOException e1) {
			LOGGER.error(e1.getMessage(), e1);
		}
		return false;
	}

	/**
	 * token 认证失败
	 *
	 * @param response
	 */
	private void onLoginFail(ServletResponse response) {
		((HttpServletResponse) response).setStatus(HttpStatus.UNAUTHORIZED.value());
		PrintWriter out = null;
		try {
			response.setCharacterEncoding("UTF-8");
			response.setContentType("application/json; charset=utf-8");
			JSONObject result = new JSONObject();
			result.put("success", "false");
			result.put("returnMessage", "unauthorized");
			out = response.getWriter();
			out.print(result.toJSONString());
			return;
		} catch (IOException e) {
			LOGGER.error(e.getMessage(), e);
		}
	}

	/**
	 * 获取请求的token
	 */
	private String getRequestToken(HttpServletRequest httpRequest) {
		// 从header中获取token
		String token = httpRequest.getHeader("sessionId");
		// 如果header中不存在token，则从参数中获取token
		if (token == null || "".equals(token)) {
			return httpRequest.getParameter("sessionId");
		}
		return token;
	}

}
